package wci.intermediate;

import wci.backend.compiler.CodeGenerator;
import wci.frontend.*;
import wci.intermediate.*;
import wci.intermediate.symtabimpl.*;
import static wci.intermediate.icodeimpl.ICodeKeyImpl.*;


public class TypeSetterVisitor extends PclParserVisitorAdapter
{
    private void setType(SimpleNode node)
    {
        int count = node.jjtGetNumChildren();
        TypeSpec type = Predefined.stringType;
        
        for (int i = 0; (i < count) && (type == Predefined.integerType); i++) {
            SimpleNode child = (SimpleNode) node.jjtGetChild(i);
            TypeSpec childType = child.getTypeSpec();
            
            if (childType == Predefined.realType) {
                type = Predefined.realType;
            }
        }
        
        node.setTypeSpec(type);
    }
    
    /**
     * Set node type when called by assignment statement 
     * 
     * <assignment statement> ::= [save] <expression> into <destination> 
     * @param node 
     */
    private void setType(ASTassignmentStatement node)
    {
    	SimpleNode expressionNode = (SimpleNode) node.jjtGetChild(0);
        SimpleNode destinationNode = (SimpleNode) node.jjtGetChild(1);
        TypeSpec expressionType = expressionNode.getTypeSpec();
        TypeSpec destinationType = destinationNode.getTypeSpec();

        if(expressionType == Predefined.stringConstantType)
        {
        	String expressionString = (String)expressionNode.getAttribute(VALUE);
        	TypeSpec destinationTypeSpec = destinationNode.getTypeSpec();
        	if(expressionString.toLowerCase().startsWith("file://") | expressionString.toLowerCase().startsWith("http://"))
        	{
        		destinationNode.setTypeSpec(Predefined.uriType);
        		node.setTypeSpec(Predefined.uriType);
        		expressionNode.setTypeSpec(Predefined.uriType);
        	}
        	else
        	{
        		destinationNode.setTypeSpec(expressionType);
          	   	node.setTypeSpec(expressionType);
        	}
        }
       else      
       {
    	   destinationNode.setTypeSpec(expressionType);
    	   node.setTypeSpec(expressionType);
       }
       
        
        
    }		
    
    public Object visit(ASTassignmentStatement node, Object data)
    {
        Object obj = super.visit(node, data);
        setType(node);
        return obj;
    }



    public Object visit(ASTmultiply node, Object data)
    {
        Object obj = super.visit(node, data);
        setType(node);
        return obj;
    }

    public Object visit(ASTdivide node, Object data)
    {
        Object obj = super.visit(node, data);
        setType(node);
        return obj;
    }
    
    public Object visit(ASTforStatement node, Object data) 
    {
    	Object obj = super.visit(node, data);
    	//For now, we will always type the variable as a string since the lists we support are lists of strings.
    	SimpleNode variableNode = (SimpleNode) node.jjtGetChild(0);
    	variableNode.setTypeSpec(Predefined.stringType);
    	
    	
    	
    	return obj;
    }
    
    public Object visit(ASTvariable node, Object data)
    {
        return data;
    }
    
    public Object visit(ASTincrementStatement node, Object data)
    { 
    //	System.out.println("shit doesn't work....");
    /*	
    	SimpleNode child = (SimpleNode) node.jjtGetChild(0);
        TypeSpec childType = child.getTypeSpec();
        
        // Automatically just set to an integer
        if( childType == Predefined.undefinedType )
        {
        	child.setTypeSpec(Predefined.integerType);
        	// start counter at 1 since inc/add was called once already
        	child.setAttribute(VALUE, 1);
        }
        */

        return data;
    }
    
    public Object visit(ASTintegerConstant node, Object data)
    {
        return data;
    }
    
    public Object visit(ASTrealConstant node, Object data)
    {
        return data;
    }

	@Override
	public Object visit(ASTinsertStatement node, Object data) {
		SimpleNode destinationNode = (SimpleNode) node.jjtGetChild(1);
        TypeSpec destinationType = destinationNode.getTypeSpec();
        if(destinationType == Predefined.undefinedType)
        	destinationNode.setTypeSpec(Predefined.listType);
		return data;
	}
}
